package db

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"sort"
	"time"
)

// 查询兑换日志
func (this ExchangeLog) GetExchangeLog(bCdk, startTime, endTime string, gameId, cdkTypeId int) (as []ExchangeLog, inValid int, err error) {

	cdkType := ReadCdkTypeCacheByIds(gameId, cdkTypeId)
	if cdkType == nil {
		return as, inValid, errors.New("ReadCdkTypeCacheByGameId cdkTypeMap == nil")
	}

	game := ReadGameCacheById(gameId)
	if game == nil {
		return as, inValid, errors.New("ReadGameCacheById game == nil")
	}

	cdkTypeEndTime, err := time.ParseInLocation("2006-01-02 15:04:05", cdkType.EndDate, time.Local)
	if err != nil {
		return
	}

	var gameCode = game.GameCode

	timeNow := time.Now()

	if timeNow.After(cdkTypeEndTime) {
		// 已经过期
		as, err = this.QueryLogFromMysql(bCdk, startTime, endTime, gameCode, cdkTypeId)
		if err != nil {
			return
		}
		inValid = 1

	} else {
		// cdkType还未过期
		as, err = this.QueryLogFromRedis(bCdk, startTime, endTime, gameCode, cdkTypeId)
		if err != nil {
			return
		}
	}

	return
}

// 从mysql中查询
func (this ExchangeLog) QueryLogFromMysql(bCdk, startTime, endTime, gameCode string, cdkTypeId int) (as []ExchangeLog, err error) {
	tableName := "ulcdkey_cdkuse.cdkuse_" + gameCode

	var sqlStr string

	if bCdk == "" {
		sqlStr = fmt.Sprintf("select bUserId,bUseTime,cdkey,cdkTypeId from %s where cdkTypeId = %d and bUseTime >= '%s' and bUseTime <= '%s'",
			tableName, cdkTypeId, startTime, endTime)
	} else {
		sqlStr = fmt.Sprintf("select bUserId,bUseTime,cdkey,cdkTypeId from %s where cdkTypeId = %d and bUseTime >= '%s' and bUseTime <= '%s' and cdkey = '%s'",
			tableName, cdkTypeId, startTime, endTime, bCdk)
	}

	log.Println("sqlStr", sqlStr)
	rows, err := db.Query(sqlStr)
	if err != nil {
		return
	}

	defer rows.Close()

	for rows.Next() {
		var a ExchangeLog
		err = rows.Scan(&a.BUserId, &a.BUseTime, &a.Cdkey, &a.CdkTypeId)
		if err != nil {
			return
		}

		as = append(as, a)

	}

	return
}

// 从Redis中查询
func (this ExchangeLog) QueryLogFromRedis(bCdk, startTime, endTime, gameCode string, cdkTypeId int) (as []ExchangeLog, err error) {
	tableName := "cdkuse_" + gameCode

	// 筛选条件1： 查询对应游戏 cdkuse 表
	cdkUseList, err := cdkDb.HGETALL(tableName)
	if err != nil {
		return
	}

	cdkTypeIdStr := fmt.Sprint(cdkTypeId)
	// key:userId value:map[string]map[string]string    cdkTypeId-cdk
	for bUserId, val := range cdkUseList {

		var data map[string]map[string]string

		err = json.Unmarshal([]byte(val), &data)
		if err != nil {
			return
		}

		cdkMap, ok := data[cdkTypeIdStr]
		if ok {
			//筛选条件2： cdkTypeId相同
			for cdk, bUseTime := range cdkMap {
				if bUseTime >= startTime && bUseTime <= endTime {

					//筛选条件3： cdk使用时间在筛选的时间范围内

					if bCdk == "" || bCdk == cdk {
						// 筛选条件4： bCdk 不为空，则查询指定cdk
						var a ExchangeLog
						a.BUserId = bUserId
						a.BUseTime = bUseTime
						a.Cdkey = cdk
						a.CdkTypeId = cdkTypeId
						as = append(as, a)
					}
				}
			}
		}
	}

	if len(as) > 100000 {
		return []ExchangeLog{}, errors.New("数据量大于10W条，请精确时间范围后再尝试")
	}

	// 按id排序
	sort.SliceStable(as, func(i, j int) bool {
		return as[i].BUserId < as[j].BUserId
	})

	return
}
